package top.wineye.spring.bean.initialization;

import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import top.wineye.spring.bean.factory.UserFactory;

import java.util.Map;


/**
 *
 */
@Configuration
public class BeanInitializationDemo {

    public static void main(String[] args) {
        /* 使用这个不可以识别到 @PostConstruct
        ApplicationContext context =
                new ClassPathXmlApplicationContext("META-INF/bean-initialization-context.xml");*/
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext();
        context.register(BeanInitializationDemo.class);
        context.refresh();

        /*
            bean 初始化方法
                1. 利用 @PostConstruct 注解实现
                2. 利用 initMethod 属性 注解和 Xml 方式都能实现 {see bean-initialization-context.xml}
                3. 实现 InitializingBean 接口

                下面通过 AbstractBeanDefinition#setInitMethod

         */

        BeanDefinitionBuilder userFactoryBeanDefinition
                = BeanDefinitionBuilder.genericBeanDefinition(UserFactory.class);

        userFactoryBeanDefinition.setInitMethodName("initByBeanDefinition");

        context.registerBeanDefinition("anotherUserFactory",
                userFactoryBeanDefinition.getBeanDefinition());

        // if this not called, which means no access to "anotherUserFactory" bean.
        // "anotherUserFactory" won't be constructed thus no init method called.
        // 666
        Map<String, UserFactory> userFactoryMap =
                context.getBeansOfType(UserFactory.class);

        // TODO: why UserFactory @PostConstruct and InitializingBean#afterPropertiesSet() init twice? init-method only once?

        System.out.println(userFactoryMap);


        context.close();
    }

    /**
     * {@link UserFactory}
     * @return UserFactory
     */
    @Bean(initMethod = "initByInitMethod")
    public UserFactory userFactory() {
        return new UserFactory();
    }
}
